package dao

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/bwmarrin/snowflake"
)

type ComicS3DAO struct {
	ComicDAO
	oss  *s3.S3
	node *snowflake.Node
}

func NewComicS3DAO(mongoDBComicDAO *MongoDBComicDAO, oss *s3.S3, node *snowflake.Node) ComicDAO {
	return &ComicS3DAO{
		ComicDAO: mongoDBComicDAO,
		oss:      oss,
		node:     node,
	}
}

func (dao *ComicS3DAO) DeleteById(ctx context.Context, comicId int64, uid int64) error {
	return dao.ComicDAO.DeleteById(ctx, comicId, uid)
}

func (dao *ComicS3DAO) Insert(ctx context.Context, comic Comic) (int64, error) {
	// 如果没有图片需要处理，直接调用底层DAO插入
	if len(comic.Draws) == 0 {
		return dao.ComicDAO.Insert(ctx, comic)
	}

	// 复制comic，避免修改原始数据
	updatedComic := comic

	// 处理每张图片
	for i, draw := range updatedComic.Draws {
		// 从临时URL获取图片数据
		resp, err := http.Get(draw.Url)
		if err != nil {
			return 0, fmt.Errorf("failed to download image: %w", err)
		}
		defer resp.Body.Close()

		if resp.StatusCode != http.StatusOK {
			return 0, fmt.Errorf("failed to download image, status code: %d", resp.StatusCode)
		}

		// 生成S3对象键
		//ext := filepath.Ext(draw.Url)
		//if ext == "" {
		//	ext = ".jpg" // 默认扩展名
		//}

		ext := dao.node.Generate().String() + ".jpeg"
		objectKey := fmt.Sprintf("comic/%d/%d%s", comic.Uid, time.Now().UnixNano(), ext)

		// 读取图片数据
		imageData, err := io.ReadAll(resp.Body)
		if err != nil {
			return 0, fmt.Errorf("failed to read image data: %w", err)
		}

		// 上传到S3
		putInput := &s3.PutObjectInput{
			Bucket:        aws.String("fable-script"), // 需要从配置中获取实际的bucket名称
			Key:           aws.String(objectKey),
			Body:          aws.ReadSeekCloser(bytes.NewReader(imageData)),
			ContentType:   aws.String("image/jpeg"), // 可以根据实际情况设置
			ContentLength: aws.Int64(int64(len(imageData))),
		}

		_, err = dao.oss.PutObjectWithContext(ctx, putInput)
		if err != nil {
			return 0, fmt.Errorf("failed to upload image to S3: %w", err)
		}

		// 生成阿里云OSS访问URL并更新
		// 使用阿里云OSS公共URL格式，前提是bucket已配置为公共读取
		// 这种URL不会过期，但要求bucket设置了适当的访问策略
		// 注意：实际使用时需要替换为真实的OSS区域域名
		publicURL := fmt.Sprintf("https://fable-script.oss-cn-beijing.aliyuncs.com/%s", objectKey)

		// 更新为阿里云OSS的公共URL
		updatedComic.Draws[i].Url = publicURL
	}

	// 调用底层DAO插入更新后的数据
	return dao.ComicDAO.Insert(ctx, updatedComic)
}

func (dao *ComicS3DAO) GetByUid(ctx context.Context, uid int64, offset int, limit int) ([]Comic, error) {
	return dao.ComicDAO.GetByUid(ctx, uid, offset, limit)
}
